package com.kingtao.service.Impl;

import com.kingtao.entry.Node;
import com.kingtao.entry.NodeGroup;
import com.kingtao.enums.NodeStatusEnums;
import com.kingtao.service.NodeGroupService;
import com.kingtao.util.CoreData;
import lombok.extern.slf4j.Slf4j;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: kingtao
 * @Date: 2023-07-27-14:58
 * @Description: 集群管理
 */
@Slf4j
public class NodeGroupServiceImpl implements NodeGroupService {

    public NodeGroup nodeGroup;

    public boolean createGroup = false;

    public boolean isCreateGroup() {
        return createGroup;
    }

    public void setCreateGroup(boolean createGroup) {
        this.createGroup = createGroup;
    }

    public NodeGroupServiceImpl() {
    }

    public void setNodeGroup(NodeGroup nodeGroup) {
        this.nodeGroup = nodeGroup;
    }

    public NodeGroup getNodeGroup() {
        return nodeGroup;
    }

    public NodeGroupServiceImpl(NodeGroup nodeGroup) {
        this.nodeGroup = nodeGroup;
    }

    //  增加新的节点
    @Override
    public void appendNode(Node node) {
        boolean success = false;
        if (nodeGroup.getNodes().contains(node)) {
            success = true;
        }
        if (!success) {
            node.setStatus(NodeStatusEnums.follower);
            node.setLeaderCurrentTerm(nodeGroup.getLeaderCurrentTerm());
            node.setSecondLeaderCurrentTerm(nodeGroup.getSecondLeaderCurrentTerm());
            nodeGroup.getNodes().add(node);
        }
    }

    //  通过  node id 移除节点
    public void removeNode(int id) {
        nodeGroup.getNodes().remove(nodeGroup.getNodeByNodeId(id));
    }

    @Override
    public void setLeader() {
        int leaderId = nodeGroup.getLeaderId();
        int secondLeaderId = nodeGroup.getSecondLeaderId();
        int maxId = 1;
        //  初始化
        if (leaderId == 0) {
            for (int i=0; i < nodeGroup.getNodes().size(); i++) {
                if (nodeGroup.getNodeByNodeId(maxId).getStatus() == NodeStatusEnums.follower){
                    maxId = nodeGroup.getNodeByNodeId(maxId).getCredit() > nodeGroup.getNodeByIndex(i).getCredit() ?
                            maxId : nodeGroup.getNodeByIndex(i).getId();
                }
            }
            nodeGroup.setLeaderId(maxId);
            nodeGroup.getNodeByNodeId(maxId).setStatus(NodeStatusEnums.leader);
        }
        else if (nodeGroup.getNodeByNodeId(leaderId).getStatus() == NodeStatusEnums.leader) {
            setSecondLeader();
            return;
        }
        //  leader 宕机
        else if (nodeGroup.getNodeByNodeId(leaderId).getStatus() == NodeStatusEnums.down) {
            removeNode(leaderId);
        }
        //  leader 为 bft
        else if ( nodeGroup.getNodeByNodeId(leaderId).getStatus() == NodeStatusEnums.bft) {
            nodeGroup.getNodeByNodeId(leaderId).setStatus(NodeStatusEnums.follower);
        }

        if (secondLeaderId != 0) {
            //  secondLeader 是否宕机
            if (nodeGroup.getNodeByNodeId(secondLeaderId).getStatus() != NodeStatusEnums.down) {
                //  secondLeader    继位
                maxId = secondLeaderId;
                nodeGroup.setLeaderId(secondLeaderId);
                nodeGroup.getNodeByNodeId(secondLeaderId).setStatus(NodeStatusEnums.leader);
                nodeGroup.setSecondLeaderId(0);
            }else {
                //  secondLeader  宕机
                removeNode(secondLeaderId);
                List<Node> followers = nodeGroup.getAllFollower();
                maxId = followers.get(0).getId();
                for (Node node : followers) {
                    maxId = nodeGroup.getNodeByNodeId(maxId).getCredit() > node.getCredit()
                            ? maxId : node.getId();
                }
                nodeGroup.setLeaderId(maxId);
                nodeGroup.getNodeByNodeId(maxId).setStatus(NodeStatusEnums.leader);
            }
        }

        //  设置 leader 的任期
        nodeGroup.addLeaderCurrentTerm();

        for (Node node : getNodeGroup().getNodes()) {
            node.setLeaderCurrentTerm(node.getLeaderCurrentTerm());
        }

        //  开始选举第二领导节点
        setSecondLeader();
    }

    //  选择第二领导节点
    @Override
    public void setSecondLeader() {

        if (nodeGroup.getNodeByNodeId(nodeGroup.getSecondLeaderId()).getStatus() == NodeStatusEnums.secondLeader) {
            return;
        }

        int maxId = 0;

        if (nodeGroup.getSecondLeaderId() == 0 || nodeGroup.getNodeByNodeId(nodeGroup.getSecondLeaderId()) == null) {
            //  获取follower的节点组
            List<Node> nodes = new ArrayList<>(nodeGroup.getAllFollower());
            maxId = nodes.get(0).getId();
            for (int i=0; i < nodes.size(); i++) {
                maxId = nodeGroup.getNodeByNodeId(maxId).getCredit() > nodes.get(i).getCredit()
                        ? maxId : nodes.get(i).getId();
            }
//            nodes.clear();
            nodeGroup.setSecondLeaderId(maxId);
            nodeGroup.getNodeByNodeId(nodeGroup.getSecondLeaderId()).setStatus(NodeStatusEnums.secondLeader);
            nodeGroup.addSecondLeaderCurrentTerm();
            for (Node node : getNodeGroup().getNodes()) {
                node.setSecondLeaderCurrentTerm(node.getSecondLeaderCurrentTerm());
            }
        }

        if (nodeGroup.getNodeByNodeId(nodeGroup.getSecondLeaderId()).getStatus() == NodeStatusEnums.down) {
            removeNode(nodeGroup.getSecondLeaderId());
        }

        //  secondLeader 作恶
        if (nodeGroup.getNodeByNodeId(nodeGroup.getSecondLeaderId()).getStatus() == NodeStatusEnums.bft) {
            nodeGroup.getNodeByNodeId(nodeGroup.getSecondLeaderId()).setStatus(NodeStatusEnums.follower);
            //  获取follower的节点组
            List<Node> nodes = new ArrayList<>(nodeGroup.getAllFollower());
            maxId = nodes.get(0).getId();
            for (int i=0; i < nodes.size(); i++) {
                maxId = nodeGroup.getNodeByNodeId(maxId).getCredit() > nodes.get(i).getCredit()
                        ? maxId : nodes.get(i).getId();
            }
            nodeGroup.setSecondLeaderId(maxId);
            nodeGroup.getNodeByNodeId(nodeGroup.getSecondLeaderId()).setStatus(NodeStatusEnums.secondLeader);
            nodeGroup.addSecondLeaderCurrentTerm();
            for (Node node : getNodeGroup().getNodes()) {
                node.setSecondLeaderCurrentTerm(node.getSecondLeaderCurrentTerm());
            }
        }
    }

    //  选择组长节点
    @Override
    public void setFollowerLeader() {
        //  存储 followerLeader 的id
        int max[] = new int[CoreData.GROUP_NUM];
        List<Node> allFollower = nodeGroup.getAllFollower();

        if (getNodeGroup().getFollowerLeaderIdMap().isEmpty()) {
            //  初始化max[], 挑选最初的followerLeaderId
            for (int i=0; i<CoreData.GROUP_NUM; ) {
                for (Node node : allFollower) {
                    if (node.getId()%CoreData.GROUP_NUM == i){
                        max[i] = node.getId();
                        i++;
                    }
                }
            }
            //  筛选followerLeaderId
            for (int i=0; i<allFollower.size(); i++) {
                int num = allFollower.get(i).getId() % CoreData.GROUP_NUM;
                max[num] = nodeGroup.getNodeByNodeId(max[num]).getCredit() > allFollower.get(i).getCredit()
                        ? max[num] : allFollower.get(i).getId();
            }
            for (int i=0; i<CoreData.GROUP_NUM; i++) {
                nodeGroup.getFollowerLeaderIdMap().put(i, max[i]);
                nodeGroup.getNodeByNodeId(max[i]).setStatus(NodeStatusEnums.followerLeader);
            }
//            log.debug("getFollowerLeaderIdMap: {}", getNodeGroup().getFollowerLeaderIdMap());
            return;
        }

        //  宕机 或者 bft 的节点 id
        int followerLeaderId = 0;

        for (int i=0; i<CoreData.GROUP_NUM; i++) {
            followerLeaderId = nodeGroup.getFollowerLeaderIdMap().get(i);
            max[i] = followerLeaderId;
            //  bft
            if (nodeGroup.getNodeByNodeId(followerLeaderId).getStatus() == NodeStatusEnums.bft) {
                nodeGroup.getNodeByNodeId(followerLeaderId).setStatus(NodeStatusEnums.follower);
                for (Node node : nodeGroup.getAllFollower()) {
                    max[i] = nodeGroup.getNodeByNodeId(max[i]).getCredit() > node.getCredit()
                            ? max[i] : node.getId();
                }
                nodeGroup.getFollowerLeaderIdMap().put(i, max[i]);
            }
            //  宕机
            else if (nodeGroup.getNodeByNodeId(followerLeaderId).getStatus() == NodeStatusEnums.down) {
                //  寻找是哪一个小组
                int temp = followerLeaderId % CoreData.GROUP_NUM;
                removeNode(followerLeaderId);
                for (Node node : allFollower) {
                    //  找到小组第一个点
                    boolean flag = false;
                    if (node.getId() % CoreData.GROUP_NUM == temp) {
                        if ( !flag ){
                            max[temp] = node.getId();
                            flag = true;
                        }
                        max[temp] = nodeGroup.getNodeByNodeId(max[temp]).getCredit() > node.getCredit()
                                ? max[temp] : node.getId();
                    }
                }
                nodeGroup.getFollowerLeaderIdMap().put(temp, max[temp]);
            }
        }
    }

    //  选择某一小组组长
    @Override
    public void setFollowerLeaderById(int id) {
        if (getNodeGroup().getNodeByNodeId(id).getStatus() == NodeStatusEnums.followerLeader) {
            log.debug("Node {} 依然为组长节点",id);
        }else {
            int groupNum = id % CoreData.GROUP_NUM;
            int followerLeaderId = 0;
            double max = 3.0;
            for (Node node : getNodeGroup().getAllFollower()) {
                if (node.getId() % CoreData.GROUP_NUM == groupNum && node.getStatus() == NodeStatusEnums.follower) {
                    if (max <= node.getCredit()) {
                        followerLeaderId = node.getId();
                        max = node.getCredit();
                    }
                }
            }
            getNodeGroup().getNodeByNodeId(followerLeaderId).setStatus(NodeStatusEnums.followerLeader);
            getNodeGroup().getFollowerLeaderIdMap().put(groupNum, followerLeaderId);
            log.debug("Node {} 为新的组长节点",followerLeaderId);
        }
    }

    //  作恶节点的惩罚
    @Override
    public void punishNode(int nodeId) {
        Node node = nodeGroup.getNodeByNodeId(nodeId);
        DecimalFormat df = new DecimalFormat("#.00");
        if (node.getStatus() == NodeStatusEnums.leader) {
            String s = df.format(node.getCredit() - 3 * CoreData.b);
            node.setCredit(Double.parseDouble(s));
            node.setStatus(NodeStatusEnums.follower);
            setLeader();
        } else if (node.getStatus() == NodeStatusEnums.secondLeader) {
            String s = df.format(node.getCredit() - 2 * CoreData.b);
            node.setCredit(Double.parseDouble(s));
            node.setStatus(NodeStatusEnums.bft);
            setSecondLeader();
        }else if ( node.getStatus() == NodeStatusEnums.followerLeader) {
            String s = df.format(node.getCredit() - 2 * CoreData.b);
            node.setCredit(Double.parseDouble(s));
            node.setStatus(NodeStatusEnums.follower);
            setFollowerLeaderById(nodeId);
        }else if ( node.getStatus() == NodeStatusEnums.follower) {
            String s = df.format(node.getCredit() - CoreData.b);
            node.setCredit(Double.parseDouble(s));
        }
        if (node.getCredit() < 0) {
            removeNode(nodeId);
            node.setStatus(NodeStatusEnums.down);
        }
    }

    //  奖励
    @Override
    public void rewardNode(int nodeId) {
        Node node = nodeGroup.getNodeByNodeId(nodeId);
        DecimalFormat df = new DecimalFormat("#.000");
        if (node.getCredit() >= CoreData.CREDIT_MAX) {
            node.setCredit(CoreData.CREDIT_MAX);
        }else {
            if (node.getStatus() == NodeStatusEnums.leader) {
                String s = df.format(node.getCredit() + 4 * CoreData.a);
                node.setCredit(Double.parseDouble(s));
            } else if (node.getStatus() == NodeStatusEnums.secondLeader) {
                String s = df.format(node.getCredit() + 3 * CoreData.a);
                node.setCredit(Double.parseDouble(s));
            }else if ( node.getStatus() == NodeStatusEnums.followerLeader) {
                String s = df.format(node.getCredit() + 2 * CoreData.a);
                node.setCredit(Double.parseDouble(s));
            }else if ( node.getStatus() == NodeStatusEnums.follower) {
                String s = df.format(node.getCredit() + CoreData.a);
                node.setCredit(Double.parseDouble(s));
            }
        }
    }

    //  返回leader
    public Node getLeader() {
        return getNodeGroup().getNodeByNodeId(getNodeGroup().getLeaderId());
    }

    //  返回secondLeader
    public Node getSecondLeader() {
        return getNodeGroup().getNodeByNodeId(getNodeGroup().getSecondLeaderId());
    }

    @Override
    public void init() {

    }

    @Override
    public void destroy() {

    }

}
